package com.sdp.irrigation.server.netty.server;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sdp.irrigation.server.netty.channel.IChannelManager;
import com.sdp.irrigation.server.netty.timer.NettyTimer;
import com.sdp.irrigation.server.property.NettyProperty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.ResourceLeakDetector;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
//import oshi.hardware.GlobalMemory;

public class NettyServer {

	private NettyProperty nettyProperty;

	private ChannelInitializer<SocketChannel> channelInitializer;

	private EventLoopGroup boss;

	private EventLoopGroup worker;

	private ServerBootstrap bootstrap;
	
	private IChannelManager channelService;

	private final static Logger logger = LoggerFactory.getLogger(NettyServer.class);

	public NettyServer(NettyProperty nettyProperty, ChannelInitializer<SocketChannel> channelInitializer, IChannelManager channelService) {
		this.nettyProperty = nettyProperty;
		this.channelInitializer = channelInitializer;
		this.channelService = channelService;
	}

	public boolean start() throws InterruptedException {
		bootstrap = new ServerBootstrap();
		boss = new NioEventLoopGroup(nettyProperty.getBossThread());
		worker = new NioEventLoopGroup(nettyProperty.getWorkerThread());
		bootstrap.group(boss, worker).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.DEBUG))
				.option(ChannelOption.SO_BACKLOG, nettyProperty.getSoBacklog())
				.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT).childHandler(channelInitializer)
				.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)// 缓冲池
				.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(16 * 1024, 32 * 1024))//设置高低水位(默认值)
				.childOption(ChannelOption.SO_KEEPALIVE, nettyProperty.isSoKeepalive());
		ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);//内存泄漏检测
		ChannelFuture future = bootstrap.bind(nettyProperty.getTcpPort()).sync();
		if (future.isSuccess()) {
			logger.info("#######################netty has started in port {}", nettyProperty.getTcpPort());
			if (nettyProperty.isMonitor()) {
				TimerTask task = new TimerTask() {

					@Override
					public void run(Timeout timeout) throws Exception {
						logger.debug("@@@@@@@@@@@当前连接数为：[{}]", channelService.getChannelSize());
						try {
//							GlobalMemory memory = ServerMonitor.getMemInfo(logger);
//							BigDecimal total = new BigDecimal(memory.getTotal());
//							BigDecimal available = new BigDecimal(memory.getAvailable());
//							BigDecimal percent = total.subtract(available).divide(total, 2, BigDecimal.ROUND_HALF_UP);
//
//							BigDecimal jvmTotal = new BigDecimal(Runtime.getRuntime().totalMemory());
//							BigDecimal jvmFree = new BigDecimal(Runtime.getRuntime().freeMemory());
//							BigDecimal jvmPercent = jvmTotal.subtract(jvmFree).divide(jvmTotal, 2, BigDecimal.ROUND_HALF_UP);
						} finally {
							NettyTimer.newTimeout(timeout.task(), 5, TimeUnit.SECONDS);
						}
						
					}
				};
				NettyTimer.newTimeout(task, 5, TimeUnit.SECONDS);
			}
			return true;
		}
		return false;
	}

	public void destroy() {
		boss.shutdownGracefully().syncUninterruptibly();
		worker.shutdownGracefully().syncUninterruptibly();
		logger.info("############################netty has closed");
	}
	public static void main(String[] args) {
		long totle = Runtime.getRuntime().totalMemory();
		long free = Runtime.getRuntime().freeMemory();
		System.out.println(totle / 1024/1024);
		System.out.println(free/1024/1024);
		while (true) {
			
		}
	}

}
